package com.frank.libandroid;

import android.util.Log;

import androidx.annotation.NonNull;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitUtil {
    public static <T> T create(String baseUrl, Class<T> clazz) {
        return new Retrofit.Builder().baseUrl(baseUrl).client(getClient())
                .addCallAdapterFactory(new LiveDataCallAdapterFactory())
                .addConverterFactory(GsonConverterFactory.create()).build().create(clazz);
    }

    public static String token = "";

    public static OkHttpClient getClient() {
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return new OkHttpClient.Builder().addInterceptor(loggingInterceptor).addInterceptor(new Interceptor() {
            @NonNull
            @Override
            public Response intercept(@NonNull Chain chain) throws IOException {
                Request originalRequest = chain.request();
                Request requestWithAuth = originalRequest.newBuilder()
                        .header("Authorization", "Bearer " + token)
                        .method(originalRequest.method(), originalRequest.body())
                        .build();
                return chain.proceed(requestWithAuth);
            }
        }).build();
    }

    private static class LiveDataCallAdapterFactory extends CallAdapter.Factory {
        @Override
        public CallAdapter<?, ?> get(Type type, Annotation[] annotations, Retrofit retrofit) {
            if (getRawType(type) != HttpLiveData.class) {
                return null;
            }
            return new HttpLiveDataCall();
        }
    }

    private static final String TAG = "RetrofitUtil";

    private static class HttpLiveDataCall implements CallAdapter<ResponseBody, HttpLiveData> {
        @Override
        public Type responseType() {
            return ResponseBody.class;
        }

        @Override
        public HttpLiveData adapt(Call<ResponseBody> call) {
            Log.d(TAG, "adapt() called with: call = [" + call.request().url() + "]" + Thread.currentThread());
            return new HttpLiveData() {
                @Override
                protected void onActive() {
                    Log.d(TAG, "adapt()111 called with: call = [" + call.request().url() + "]");
                    super.onActive();
                    if (call.isExecuted()) {
                        return;
                    }
                    Log.d(TAG, "adapt()222 called with: call = [" + call.request().url() + "]");
                    HttpResult httpResult = new HttpResult();
                    call.enqueue(new retrofit2.Callback<ResponseBody>() {
                        @Override
                        public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
                            if (response.isSuccessful()) {
                                httpResult.isSuccessful = true;
                                httpResult.responseBody = response.body();
                            } else {
                                httpResult.errorCode = response.code();
                                httpResult.errorMessage = response.message();
                            }
                            postValue(httpResult);
                        }

                        @Override
                        public void onFailure(Call<ResponseBody> call, Throwable t) {
                            httpResult.errorCode = 500;
                            httpResult.errorMessage = t.getMessage();
                            postValue(httpResult);
                        }
                    });
                }
            };
        }
    }
}
